import 'package:flutter/material.dart';

const Duration _kExpand = Duration(milliseconds: 200);

class FxExpansionTile extends StatefulWidget {
  const FxExpansionTile(
      {Key? key,
        this.leading,
        required this.title,
        this.subtitle,
        this.onExpansionChanged,
        this.children = const <Widget>[],
        this.trailing,
        this.initiallyExpanded = false,
        this.maintainState = false,
        this.tilePadding,
        this.tileColor,
        this.expandedCrossAxisAlignment,
        this.expandedAlignment,
        this.childrenPadding,
        this.backgroundColor,
        this.collapsedBackgroundColor,
        this.textColor,
        this.collapsedTextColor,
        this.iconColor,
        this.collapsedIconColor,
        this.dividerColor,
        this.showReverseDivider = false,
        this.horizontalTitleGap = 0.0, this.tileMargin, this.decoration, this.titleBackgroundColor, this.leadingRotate = true, this.trailingRotate = true})
      : assert(
  expandedCrossAxisAlignment != CrossAxisAlignment.baseline,
  'CrossAxisAlignment.baseline is not supported since the expanded children '
      'are aligned in a column, not a row. Try to use another constant.',
  ),
        super(key: key);

  final Widget? leading;

  final Widget title;

  final Widget? subtitle;

  final ValueChanged<bool>? onExpansionChanged;

  final List<Widget> children;

  final Color? backgroundColor;

  final Color? titleBackgroundColor;

  final Color? collapsedBackgroundColor;

  final Widget? trailing;

  final bool initiallyExpanded;

  final bool maintainState;

  final EdgeInsetsGeometry? tilePadding;

  final EdgeInsetsGeometry? tileMargin;

  final double horizontalTitleGap;

  final Alignment? expandedAlignment;

  final CrossAxisAlignment? expandedCrossAxisAlignment;

  final EdgeInsetsGeometry? childrenPadding;

  final Color? iconColor;

  final Color? collapsedIconColor;

  final Color? textColor;

  final Color? collapsedTextColor;

  final Color? dividerColor;

  final Color? tileColor;

  final Decoration? decoration;

  final bool? leadingRotate;

  final bool? trailingRotate;

  final bool? showReverseDivider;

  @override
  _FxExpansionTileState createState() => _FxExpansionTileState();
}

class _FxExpansionTileState extends State<FxExpansionTile>
    with SingleTickerProviderStateMixin {
  static final Animatable<double> _easeOutTween =
  CurveTween(curve: Curves.easeOut);
  static final Animatable<double> _easeInTween =
  CurveTween(curve: Curves.easeIn);
  static final Animatable<double> _halfTween =
  Tween<double>(begin: 0.0, end: 0.5);
  static final Animatable<double> _quarterTween =
  Tween<double>(begin: 0.0, end: 0.25);

  final ColorTween _borderColorTween = ColorTween();
  final ColorTween _headerColorTween = ColorTween();
  final ColorTween _iconColorTween = ColorTween();
  final ColorTween _backgroundColorTween = ColorTween();

  late AnimationController _controller;
  late Animation<double> _iconTurns;
  late Animation<double> _leadingIconTurns;
  late Animation<double> _heightFactor;
  late Animation<Color?> _backgroundColor;

  bool _isExpanded = false;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(duration: _kExpand, vsync: this);
    _heightFactor = _controller.drive(_easeInTween);
    _iconTurns = _controller.drive(_halfTween.chain(_easeInTween));
    _leadingIconTurns = _controller.drive(_quarterTween.chain(_easeInTween));
    _backgroundColor =
        _controller.drive(_backgroundColorTween.chain(_easeOutTween));

    _isExpanded = PageStorage.of(context).readState(context) as bool? ??
        widget.initiallyExpanded;
    if (_isExpanded) _controller.value = 1.0;
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _handleTap() {
    setState(() {
      _isExpanded = !_isExpanded;
      if (_isExpanded) {
        _controller.forward();
      } else {
        _controller.reverse().then<void>((void value) {
          if (!mounted) return;
          setState(() {
            // Rebuild without widget.children.
          });
        });
      }
      PageStorage.of(context).writeState(context, _isExpanded);
    });
    widget.onExpansionChanged?.call(_isExpanded);
  }

  Widget _buildChildren(BuildContext context, Widget? child) {

    return Container(
      decoration: BoxDecoration(
        color: _backgroundColor.value ?? Colors.transparent,
      ),
      child: Column(
        children: <Widget>[
          GestureDetector(
            onTap: _handleTap,
            child: Container(
                color: widget.titleBackgroundColor ?? Colors.white,
                margin: widget.tileMargin ?? const EdgeInsets.all(0),
                decoration: widget.decoration,
                padding:widget.tilePadding ?? const EdgeInsets.fromLTRB(15, 15, 15, 10),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        widget.leadingRotate! == true ? RotationTransition(
                          turns: _leadingIconTurns,
                          child: widget.leading ??  const Icon(Icons.play_arrow,
                              size: 14, color: Color(0xFF999999)),
                        ) : widget.leading ??  const Icon(Icons.play_arrow,
                            size: 14, color: Color(0xFF999999)),
                        Expanded(child: widget.title),
                        widget.trailingRotate! == true ? RotationTransition(
                          turns: _iconTurns,
                          child:widget.trailing ?? Icon(Icons.expand_more_rounded, color: widget.tileColor ?? Colors.black,size: 18),
                        ) : widget.trailing ?? Icon(Icons.expand_more_rounded, color: widget.tileColor ?? Colors.black,size: 18),
                      ],
                    ),
                    Padding(padding: const EdgeInsets.fromLTRB(20, 0, 0, 0),
                      child: widget.subtitle ?? Container(),)
                  ],
                )),
          ),
          Visibility(
            visible: widget.showReverseDivider! ? !_isExpanded : _isExpanded,
            child: Container(height: 0.5,color: widget.dividerColor ?? const Color(0xFFE9E9E9),),),
          ClipRect(
            child: Align(
              alignment: widget.expandedAlignment ?? Alignment.center,
              heightFactor: _heightFactor.value,
              child: child,
            ),
          ),
        ],
      ),
    );
  }

  @override
  void didChangeDependencies() {
    final ThemeData theme = Theme.of(context);
    final ColorScheme colorScheme = theme.colorScheme;
    _borderColorTween.end = widget.dividerColor ?? theme.dividerColor;
    _headerColorTween
      ..begin = widget.collapsedTextColor ?? theme.textTheme.subtitle1!.color
      ..end = widget.textColor ?? colorScheme.secondary;
    _iconColorTween
      ..begin = widget.collapsedIconColor ?? theme.unselectedWidgetColor
      ..end = widget.iconColor ?? colorScheme.secondary;
    _backgroundColorTween
      ..begin = widget.collapsedBackgroundColor
      ..end = widget.backgroundColor;
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    final bool closed = !_isExpanded && _controller.isDismissed;
    final bool shouldRemoveChildren = closed && !widget.maintainState;

    final Widget result = Offstage(
      offstage: closed,
      child: TickerMode(
        enabled: !closed,
        child: Padding(
          padding: widget.childrenPadding ?? EdgeInsets.zero,
          child: Column(
            crossAxisAlignment:
            widget.expandedCrossAxisAlignment ?? CrossAxisAlignment.center,
            children: widget.children,
          ),
        ),
      ),
    );

    return AnimatedBuilder(
      animation: _controller.view,
      builder: _buildChildren,
      child: shouldRemoveChildren ? null : result,
    );
  }
}
